/*
 * This file is part of rapidRest.
 *
 * rapidRest is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * rapidRest is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with rapidRest.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package br.com.rapidrest.chain;

import java.io.IOException;
import java.lang.reflect.Method;

import javax.annotation.security.RolesAllowed;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import br.com.rapidrest.exception.ChainException;
import br.com.rapidrest.request.RequestScope;

public class RolesAllowedCommand implements Command {

	/**
	 * Expects to be executed using a {@link BasicChainContext}, in wich
	 * {@link RequestScope#getBeanClass()} should not return null, and will
	 * consider {@link BasicChainContext#getMethod()} if not null.
	 */
	@Override
	public void execute(Chain chain) throws ChainException {
		BasicChainContext context = (BasicChainContext) chain.getContext();

		Class<?> beanClass = context.getRequestScope().getBeanClass();
		Method method = context.getMethod();

		boolean isClassAnnottated = beanClass
				.isAnnotationPresent(RolesAllowed.class);
		boolean isMethodAnnottated = false;
		if (method != null) {
			isMethodAnnottated = method.isAnnotationPresent(RolesAllowed.class);
		}

		RolesAllowed rolesAllowed = null;
		if (isClassAnnottated && isMethodAnnottated) {
			rolesAllowed = method.getAnnotation(RolesAllowed.class);
		} else if (isClassAnnottated) {
			rolesAllowed = beanClass.getAnnotation(RolesAllowed.class);
		} else if (isMethodAnnottated) {
			rolesAllowed = method.getAnnotation(RolesAllowed.class);
		}

		if (rolesAllowed != null) {
			HttpServletRequest request = context.getRequest();
			String[] roles = rolesAllowed.value();
			boolean allowed = false;
			for (String role : roles) {
				if (request.isUserInRole(role)) {
					allowed = true;
					break;
				}
			}
			if (!allowed) {
				try {
					context.getResponse().sendError(
							HttpServletResponse.SC_FORBIDDEN);
					return;
				} catch (IOException e) {
					throw new ChainException(e);
				}
			}
		}
		chain.proceed();
	}
}